--[[
Author: wangxiaoyan
Date: 2020-11-02 14:26:45
LastEditTime: 2021-01-18 16:48:20
FilePath: \Lua\Battle\BattleSceneCacheResouce.lua

存储战斗和冒险公用的资源，切换场景时不需要再次加载
包括
1. 角色模型
2. 角色技能
3. 后续优化...

注意
在进入战斗和进入冒险都要比对一下
--]]
require 'Common/Class'

BattleSceneCacheResouce = Class("BattleSceneCacheResouce")
local _M = BattleSceneCacheResouce

_M.NoDeletePath = {"CameraMain","CameraRound","MaskPlane"}

function _M:ctor()
    self._cacheResList = {}             -- 总缓存资源{路径={对象1,对象2,...}}
    self._reUseResList = {}             -- 当前可重用部分和_cacheResList结构一样
end
function _M:dtor()
    -- 整个游戏生命周期都存在，所以不需要清理
end

-- 删除不需要缓存的资源
---@param objList 缓存对象
---@param ignoreObjList 忽略列表
function _M:ClearCacheObj(saveObjList,ignoreObjList)
    -- 刷选
    if true then
        return
    end
    local clearResList = {}
    for pathi, objList in pairs(self._cacheResList) do
        for pathj, obj in pairs(objList) do
            if table.containsIndex(ignoreObjList,obj) == 0 then 
                if clearResList[pathi] == nil then 
                    clearResList[pathi] = {}
                end
                table.insert(clearResList[pathi],obj)
            end
        end
    end
    table.clear(self._cacheResList)

    for pathi, objList in pairs(clearResList) do
        if self._cacheResList[pathi] == nil then 
            self._cacheResList[pathi] = {}
        end
        if #objList > 0 then 
            if saveObjList == nil then
                for index, obj in ipairs(objList) do
                    table.insert(self._cacheResList[pathi],obj) 
                end
                table.clear(objList)
            else
                for index, obj in pairs(saveObjList) do
                    local inIndex = table.containsIndex(objList,obj)
                    table.insert(self._cacheResList[pathi],obj) 
                    if inIndex > 0 then 
                        table.remove(objList,inIndex)
                    end
                end 
            end
        end
    end

    self:ClearHelper(clearResList)
end

-- 删除不需要缓存的资源
---@param resList 需要缓存的资源
function _M:ClearCacheRes(resList)
    -- 刷选
    if true then
        return
    end
    local clearResList = {}
    for key, value in pairs(self._cacheResList) do
        clearResList[key] = value
    end
    table.clear(self._cacheResList)
    for pathi, objList in pairs(clearResList) do
        if self._cacheResList[pathi] == nil then 
            self._cacheResList[pathi] = {}
        end
        if #objList > 0 then
            if resList == nil then
                local obj = table.remove(objList)
                if obj then
                    table.insert(self._cacheResList[pathi],obj)
                end
                --for index, value in ipairs(objList) do
                --    table.insert(self._cacheResList[pathi],value)
                --end
                --table.clear(objList)
            else
                for pathj, _type in pairs(resList) do
                    local pathj = self:GetRealPath(pathj)
                    if pathi == pathj then 
                        local obj = table.remove(objList)
                        if obj then 
                            table.insert(self._cacheResList[pathi],obj) 
                        end
                    end
                end 
            end
        end
    end

    self:ClearHelper(clearResList)
end

function _M:ClearHelper(clearResList)
    -- 当前可重用资源
    if true then 
        return 
    end
    table.clear(self._reUseResList)
    for pathi, objList in pairs(self._cacheResList) do
        if self._reUseResList[pathi] == nil then 
        self._reUseResList[pathi] = {}
        end
        for key, obj in pairs(objList) do
            if not HelperFunc.IsNull(obj) then 
                obj.gameObject:SetActive(false)
                table.insert(self._reUseResList[pathi],obj) 
            end
        end
    end

    -- 删除
    for key, objList in pairs(clearResList) do
        for key, vs in pairs(objList) do
            if not HelperFunc.IsNull(vs) then 
                destroy(vs)
            end
        end
    end
end

-- 获取缓存对象
function _M:GetCacheObj(path)
    local path = self:GetRealPath(path)
    for key, objList in pairs(self._reUseResList) do
        if key == path then 
            local obj = table.remove(objList,1)
            for index, tempObj in pairs(self._cacheResList[path]) do
                if obj == tempObj then 
                    table.remove(self._cacheResList[path],index)
                    break
                end
            end
            if not HelperFunc.IsNull(obj) then
                obj.gameObject:SetActive(true)
                return obj
            else
                return nil
            end
        end
    end
    return nil
end

-- 增加加载对象
function _M:AddCacheObj(path,obj)
    if HelperFunc.IsNull(obj) then
        return
    end
    local path = self:GetRealPath(path)
    obj = obj.gameObject
    if self._cacheResList[path] == nil then 
        self._cacheResList[path] = {}
    end
    if not table.contains(self._cacheResList[path],obj) then 
        table.insert(self._cacheResList[path],obj) 
    end
end

-- 增加可使用对象
function _M:AddReUseObj(path,obj)
    if HelperFunc.IsNull(obj) or true then
        return
    end
    local path = self:GetRealPath(path)
    obj = obj.gameObject
    self:AddCacheObj(path,obj)
    if self._reUseResList[path] == nil then 
        self._reUseResList[path] = {}
    end
    if not table.contains(self._reUseResList[path],obj) then 
        table.insert(self._reUseResList[path],obj) 
    end
end

function _M:IsCacheObj(obj)
    if table.contains(self.NoDeletePath,obj.name) then 
        return true
    end

    for key, objList in pairs(self._cacheResList) do
        if table.contains(objList,obj) then 
            return true
        end
    end
    return false
end

function _M:GetRealPath(path)
    local index = string.find(path,"#")
    if index and index > 0 then
        path = string.sub(path,0,index-1)
    end
    local cloneIndex = string.find(path,"(Clone)")
    if cloneIndex and cloneIndex > 0 then 
       path = string.sub(path,1,cloneIndex-2) 
    end
    local path = string_split(path,"/")
    path = path[#path]
    return path
end
function _M:InitMapInstance(mapInstance, isBossBattle, pos)
    self:SaveMapInstance(mapInstance)
    if not mapInstance then
        return nil
    end
    local show
    local hide
    mapInstance:SetActive(true)
    if isBossBattle then
        mapInstance.transform:SetParent(panelMgr.BattleRound.transform, false)
    else
        mapInstance.transform:SetParent(panelMgr.BattleMain.transform, false)
    end
    local tran = mapInstance.transform

    Util.Lua_SetLocalPositionXYZ(tran, 0, 0, 0)
    if pos == nil then
        local map = tran.transform:Find("BattleMap")
        pos = map.localPosition.x;
    end
    if isBossBattle then
        show = tran:Find("BattleMap")
        Util.Lua_SetLocalPositionXYZ(show,tonumber(pos),show.localPosition.y,show.localPosition.z);
        hide = tran:Find("Map")
    else
        hide = tran:Find("BattleMap")
        show = tran:Find("Map")
    end
    if show then
        show.gameObject:SetActive(true)
    else
        --logError(mapInstance.name .. "地图找不到节点：" .. (isBossBattle and "BattleMap" or "Map"))
    end
    if hide then
        hide.gameObject:SetActive(false)
    else
        --logError(mapInstance.name .. "地图找不到节点：" .. (isBossBattle and "Map" or "BattleMap"))
    end
    return show
end

function _M:SaveMapInstance(instance)
    if self.mapInstance and self.mapInstance ~= instance then
       --GameObject.DestroyImmediate(self.mapInstance);
       self.mapInstance = nil
    end
    self.mapInstance = instance
    self:RemoveMapFromParent()
    
end

function _M:RemoveMapFromParent()
    if not HelperFunc.IsNull(self.mapInstance) and self.mapInstance.transform then
        self.mapInstance.transform:SetParent(nil, false)
        self.mapInstance:SetActive(false)
    end
end

function _M:GetMapInstance()
    if HelperFunc.IsNull(self.mapInstance) then
        return nil
    end
    return self.mapInstance
end

function _M:PrepareLoadRes()
    --后面改做法吧
    self:PrepareLoadMapRes()
    self:PrepareMyTeamRes(self.myFormations)
    self:PrepareMonsterTeamRes(self.enemyFormations)
    self.myFormations = nil
    self.enemyFormations = nil
end
function _M:PrepareLoadMapRes()
    --map
    --[[if BattlePlaybackManager.GetFightType() ~= EnumConst.FightTypeConst.DUNGEON then
        return
    end
    local bossMap = logicMgr.MapManager.getBossMapName();
    if bossMap ~= nil then
        local mapInstance = BattleSceneCacheResouce:GetMapInstance()
        if mapInstance and mapInstance.name == bossMap.."(Clone)" then
            BattleSceneCacheResouce:InitMapInstance(mapInstance,true)
        else
            FightManager.resList["Prefabs/MapPref/"..bossMap] = "Map"
            destroy(mapInstance)
            BattleSceneCacheResouce:SaveMapInstance(nil)
        end
    end]]
end
function _M:CacheBattleFormation(myForms,enemyForms)
    self.myFormations = myForms
    self.enemyFormations = enemyForms
end

--准备预载我方队伍资源
function _M:PrepareMyTeamRes(formations)
    if not formations then return end
    for k,v in pairs(formations) do
        for k2,v2 in pairs(v) do
            local id = tostring(v2)
            local data = HeroManager.getHeroDatabyPartnerId(id,true)
            if data then
                local cfg = dataTable.getDataTableByStringId("t_hero",data.partnerModelId)
                FightManager.addModelRes(cfg.f_HeroID);
                FightManager.addSkill(cfg.f_HeroAtk,dataTable.getDataTableByStringId("t_skillshow",cfg.f_HeroAtk))
                --后面应根据星级加载技能
                for i = 1,2 do
                    local id = cfg["f_HeroSkill"..i]
                    FightManager.addSkill(id,dataTable.getDataTableByStringId("t_skillshow",id))
                end
            end
        end
    end
    FightManager.PreloadBattleSceneRes()
end
--准备预载敌方队伍资源
function _M:PrepareMonsterTeamRes(formations)
    if not formations then return end
    for k,v in pairs(formations) do
        for k2,v2 in pairs(v) do
            local id = v2.partnerModelId
            local cfg = dataTable.getDataTableByStringId("t_hero",id)
            if cfg then
                FightManager.addModelRes(cfg.f_HeroID);
                FightManager.addSkill(cfg.f_HeroAtk,dataTable.getDataTableByStringId("t_skillshow",cfg.f_HeroAtk))
                for i = 1,2 do
                    local id = cfg["f_HeroSkill"..i]
                    FightManager.addSkill(id,dataTable.getDataTableByStringId("t_skillshow",id))
                end
            end
        end

    end
end
function BattleSceneCacheResouce:OnDestroy()
    if self.mapInstance  then
        destroy(self.mapInstance)
        self.mapInstance = nil
        self:SaveMapInstance(nil)
    end
    self:ClearCacheRes()
end
BattleSceneCacheResouce = _M.New()